#!/usr/bin/python
# Copyright 2016 Red Hat, Inc.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

import argparse
import logging
import os
import shutil
import sys
from ipalib import api, errors
from ipapython import version
from novajoin import configure_ipa
from novajoin.errors import ConfigurationError


IPACONF = '/etc/ipa/default.conf'

logging.basicConfig(format='%(message)s')
logger = logging.getLogger()


if __name__ == '__main__':

    logger.setLevel(logging.INFO)
    try:
        parser = argparse.ArgumentParser(
            description='novajoin Install Options'
        )
        parser = configure_ipa.ipa_options(parser)
        opts = parser.parse_args()
        configure_ipa.validate_options(opts)
    except ConfigurationError as e:  # pylint: disable=broad-except
        logger.info(str(e))          # emit message to console
        logger.debug(e, exc_info=1)  # add backtrace information to logfile

        logger.info('Installation aborted.')
        sys.exit(1)

    if not opts.precreate and not os.path.exists('/etc/ipa/default.conf'):
        sys.exit('Must be enrolled in IPA or see precreate')

    if opts.debug:
        logger.setLevel(logging.DEBUG)

    args = {'context': 'novajoin'}
    if opts.precreate:
        if opts.domain:
            args['domain'] = opts.domain
        if opts.realm:
            args['realm'] = opts.realm
        if opts.server:
            args['xmlrpc_uri'] = u'https://%s/ipa/json' % opts.server

    precreate_opts_specified = (opts.precreate and opts.domain
                                and opts.realm and opts.server)

    # suppress the Forwarding messages from ipa
    # This is not needed in versions newer than 4.7
    if version.NUM_VERSION < 40600:
        from ipapython.ipa_log_manager import log_mgr
        console = log_mgr.get_handler('console')
        console.setLevel(logging.WARN)

    novajoin = configure_ipa.NovajoinRole(user=opts.user,
                                          hostname=opts.hostname)

    ccache_dir = None
    if not opts.no_kinit:
        if precreate_opts_specified:
            krb5_conf = novajoin.create_krb5_conf(opts)
            os.environ['KRB5_CONFIG'] = krb5_conf
        else:
            krb5_conf = None
        try:
            ccache_dir = novajoin.kinit(opts.principal, opts.realm,
                                        opts.password, krb5_conf)
            # We use the ccache that we just created inside the kinit
            # function.
            os.environ['KRB5CCNAME'] = novajoin.ccache_name
        except ConfigurationError:
            if krb5_conf:
                os.remove(krb5_conf)

    nss_db = None
    cafile = None

    if precreate_opts_specified:
        # IPA v4.5.0 switched client from NSS to OpenSSL
        if version.NUM_VERSION >= 40500:
            cafile = novajoin.create_cafile(opts.server, opts.realm)
            # Workaround for https://pagure.io/freeipa/issue/7145
            try:
                args['tls_ca_cert'] = cafile.decode('UTF-8')
            except AttributeError:
                args['tls_ca_cert'] = cafile
        else:
            nss_db = novajoin.create_nssdb(opts.server, opts.realm)
            try:
                args['nss_dir'] = nss_db.secdir.decode('UTF-8')
            except AttributeError:
                args['nss_dir'] = nss_db.secdir

    api.bootstrap(**args)
    api.finalize()

    logging.debug('Connect to IPA backend')
    try:
        if cafile:
            api.Backend.rpcclient.connect(ca_certfile=cafile)
        elif nss_db:
            api.Backend.rpcclient.connect(nss_dir=nss_db.secdir)
        else:
            api.Backend.rpcclient.connect()
    except errors.CCacheError:
        if nss_db:
            nss_db.close()
        sys.exit("No Kerberos credentials")

    novajoin.configure_ipa(opts.precreate, opts.otp_filename)

    if nss_db:
        nss_db.close()
    if cafile:
        os.remove(cafile)
    if krb5_conf:
        os.remove(krb5_conf)
    if ccache_dir:
        shutil.rmtree(ccache_dir)
